package com.example.utils;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtParserBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.security.Keys;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;

import javax.crypto.SecretKey;
import java.util.Date;
import java.util.Map;

/**
 * Description:JWT工具包
 * User: 阿宾
 * Date: 2025-05-15
 * Time: 21:06
 */
@Slf4j
public class JwtUtils {

    //1小时（毫秒为单位）
    public static final long JWT_EXPIRATION = 60*60*1000;

    //密钥,这个是用来校验生成的JWT令牌的合法性
    //需要保持256位，否则不能设置为密钥，所以需要使用特定方法来创建一个密钥,创建方法genKey
    private static final String secretStr = "s2UdiIXRuE9FjOKBQcs4vT8f8Olv1RN+ZDUuCrhQR5o=";
    //生成安全密钥
    private static final SecretKey KEY = Keys.hmacShaKeyFor(Decoders.BASE64.decode(secretStr));

    /**
     * 生成token
     */
    public static String genJwtToken(Map<String,Object> claim){
        String jwt = Jwts.builder()
                .setClaims(claim)//设置JWt中的负载内容，由键值对组成
                .setExpiration(new Date(System.currentTimeMillis()
                        + JWT_EXPIRATION)) //设置过期时间
                .signWith(KEY) //设置签名算法
                .compact(); //用来返回JWT字符串

        return jwt;
    }


    /**
     * 校验token
     * @param token 生成的JWT令牌
     * @return null表示校验失败
     */
    public static Claims parseJWT(String token){
        //检验token长度
        if(!StringUtils.hasLength(token)){
            return null;
        }
        //创建解析器，设置签名密钥
        JwtParserBuilder jwtParserBuilder = Jwts.parserBuilder().setSigningKey(KEY);
        Claims claims = null;
        try{
            //解析token
            claims = jwtParserBuilder.build().parseClaimsJws(token).getBody();
        }catch (Exception e){
            log.error("令牌解析错误：{}",token);
            return null;
        }
        return claims;
    }

    /**
     * 通过token获取用户Id
     * @param token
     * @return
     */
    public static Integer getIdByToken(String token){
        Claims claims = parseJWT(token);
        if(claims != null){
            Integer userId = (Integer)claims.get("id");
            if(userId > 0){
                return userId;
            }
        }
        return null;
    }
}
